home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 26 / CU Amiga Magazine's Super CD-ROM 26 (1998)(EMAP Images)(GB)[!][issue 1998-09].iso / CUCD / PowerPC / uae-0.8.4 / amiga / source / undms.c < prev   
C/C++ Source or Header  |  1998-06-06  |  36KB  |  1,087 lines

  1. /* $VER: undms 1.0 (6.2.98) */
  2. /* Created: 30.1.98 */
  3.  
  4. /* DMS Extract in (supposedly) portable C.                               */
  5.  
  6. /* Compile with:                                                         */
  7. /* gcc undms.c -oundms -O2                                               */
  8.  
  9. /* I coded this to make sure it would work with unsigned bytes to try    */
  10. /* and make it as portable as possible. It should be transparent to      */
  11. /* byte order and alignment. Checking of EOF and number of tracks is     */
  12. /* quite primitive and could no doubt be improved. The decrunch          */
  13. /* functions all check for out of bounds data so no overwriting of       */
  14. /* buffers should be possible, even for severly corrupt data.            */
  15. /* Decryption is NOT supported at this time. (btw. it is very weak and   */
  16. /* there is even code in some DMS programs which allow a brute force     */
  17. /* scanning of passwords)                                                */
  18.  
  19. /* --------------------------------------------------------------------- */
  20.  
  21. #include <stdio.h>
  22.  
  23. /* --------------------------------------------------------------------- */
  24.  
  25. int DEBUG;
  26.  
  27. #define BUFFERSIZE 16000
  28.  
  29. unsigned char pack_buffer[BUFFERSIZE];
  30. unsigned char unpack_buffer[BUFFERSIZE];
  31.  
  32. unsigned char info_header[4];
  33. unsigned char archive_header[52];
  34. unsigned char track_header[20];
  35.  
  36. unsigned char quick_buffer[256];
  37.  
  38. unsigned char medium_buffer[16384];
  39.  
  40. unsigned char deep_buffer[16384];
  41. unsigned short deep_weights[628];
  42. unsigned short deep_symbols[628];
  43. unsigned short deep_hash[942];
  44.  
  45. unsigned char heavy_buffer[8192];
  46. unsigned short heavy_literal_table[5120];
  47. unsigned short heavy_offset_table[320];
  48. unsigned char heavy_literal_len[512];
  49. unsigned char heavy_offset_len[32];
  50.  
  51. unsigned int quick_local;
  52. unsigned int medium_local;
  53. unsigned int deep_local;
  54. unsigned int heavy_local;
  55. unsigned int heavy_last_offset;
  56.  
  57. unsigned int pack_size;
  58. unsigned int rle_size;
  59. unsigned int unpack_size;
  60. unsigned int high_track;
  61. unsigned int no_clear_flag;
  62.  
  63. /* --------------------------------------------------------------------- */
  64.  
  65. static const unsigned short CRCTable[256]=
  66. {
  67.    0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
  68.    0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440,
  69.    0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40,
  70.    0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841,
  71.    0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,
  72.    0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
  73.    0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,
  74.    0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
  75.    0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,
  76.    0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
  77.    0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,
  78.    0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
  79.    0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,
  80.    0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
  81.    0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,
  82.    0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
  83.    0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,
  84.    0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
  85.    0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,
  86.    0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
  87.    0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,
  88.    0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
  89.    0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,
  90.    0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
  91.    0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,
  92.    0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
  93.    0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,
  94.    0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
  95.    0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,
  96.    0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
  97.    0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,
  98.    0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040
  99. };
  100.  
  101. /* --------------------------------------------------------------------- */
  102.  
  103. static const unsigned char table_one[256]=
  104. {
  105.    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
  107.    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
  108.    6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,
  109.    10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,
  110.    12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,
  111.    16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,
  112.    20,20,20,20,21,21,21,21,22,22,22,22,23,23,23,23,
  113.    24,24,25,25,26,26,27,27,28,28,29,29,30,30,31,31,
  114.    32,32,33,33,34,34,35,35,36,36,37,37,38,38,39,39,
  115.    40,40,41,41,42,42,43,43,44,44,45,45,46,46,47,47,
  116.    48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
  117. };
  118.  
  119. static const unsigned char table_two[256]=
  120. {
  121.    3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  122.    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  123.    4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  124.    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  125.    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  126.    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  127.    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  128.    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
  129. };
  130.  
  131. /* --------------------------------------------------------------------- */
  132.  
  133. unsigned int mycrc(unsigned char *memory, unsigned int length)
  134. {
  135.    register unsigned int temp = 0;
  136.  
  137.    while(length--)
  138.       temp = CRCTable[(temp ^ *memory++) & 255] ^ ((temp >> 8) & 255);
  139.  
  140.    return (temp & 65535);
  141. }
  142.  
  143. /* --------------------------------------------------------------------- */
  144.  
  145. unsigned int mysimplecrc(unsigned char *memory, unsigned int length)
  146. {
  147.    register unsigned int temp = 0;
  148.  
  149.    while(length--) temp = temp + (*memory++ & 255);
  150.  
  151.    return (temp & 65535);
  152. }
  153.  
  154. /* --------------------------------------------------------------------- */
  155.  
  156. int crunch_store(unsigned char *source, unsigned char *source_end,
  157.                  unsigned char *destination, unsigned char *destination_end)
  158. {
  159.    while((destination < destination_end) && (source < source_end))
  160.       *destination++ = *source++;
  161.  
  162. if(DEBUG)printf(" ...store %s",((source != source_end) || (destination != destination_end)) ? "bad" : "good");
  163.    return((source != source_end) || (destination != destination_end));
  164. }
  165.  
  166. /* --------------------------------------------------------------------- */
  167.  
  168. int crunch_rle(unsigned char *source, unsigned char *source_end,
  169.                unsigned char *destination, unsigned char *destination_end)
  170. {
  171.    register unsigned char temp;
  172.    register int count;
  173.  
  174.    while((destination < destination_end) && (source < source_end))
  175.    {
  176.       if((temp = *source++) != 144) /* crunch_dle */
  177.       {
  178.          *destination++ = temp;
  179.       }
  180.       else if((count = *source++) == 0)
  181.       {
  182.          *destination++ = temp;
  183.       }
  184.       else
  185.       {
  186.          temp = *source++;
  187.          if(count == 255)
  188.          {
  189.             count = *source++ << 8;
  190.             count += *source++;
  191.          }
  192.          while((destination < destination_end) && (count--))
  193.             *destination++ = temp;
  194.       }
  195.    } /* while */
  196.  
  197. if(DEBUG)printf(" ...runlength %s",((source != source_end) || (destination != destination_end)) ? "bad" : "good");
  198.    return((source != source_end) || (destination != destination_end));
  199. }
  200.  
  201. /* --------------------------------------------------------------------- */
  202.  
  203. int crunch_quick(unsigned char *source, unsigned char *source_end,
  204.                unsigned char *destination, unsigned char *destination_end)
  205. {
  206.    register unsigned int control = 0;
  207.    register int shift = 0;
  208.    int count, offset;
  209.  
  210.    quick_local += 5; /* i have no idea why it adds 5 */
  211.    if(!no_clear_flag)
  212.       for(quick_local = count = 0; count < 256; count++)
  213.          quick_buffer[count] = 0;
  214.  
  215.    while((destination < destination_end) && (source < source_end))
  216.    {
  217.       control <<= 9; /* all codes are at least 9 bits long */
  218.       if((shift += 9) > 0)
  219.       {
  220.          control += *source++ << (8 + shift);
  221.          control += *source++ << shift;
  222.          shift -= 16;
  223.       }
  224.       if(control & 33554432)
  225.       {
  226.          *destination++ = quick_buffer[quick_local++ & 255] = control >> 16;
  227.       }
  228.       else
  229.       {
  230.          control <<= 2; /* 2 extra bits for length */
  231.          if((shift += 2) > 0)
  232.          {
  233.             control += *source++ << (8 + shift);
  234.             control += *source++ << shift;
  235.             shift -= 16;
  236.          }
  237.          count = ((control >> 24) & 3) + 2;
  238.          offset = quick_local - ((control >> 16) & 255) - 1;
  239.          while((destination < destination_end) && (count--))
  240.             *destination++ = quick_buffer[quick_local++ & 255] =
  241.                              quick_buffer[offset++ & 255];
  242.       }
  243.    } /* while */
  244.  
  245. if(DEBUG)printf(" ...quick %s",((source > source_end) || (destination != destination_end)) ? "bad" : "good", source, source_end, destination, destination_end);
  246.    return((source > source_end) || (destination != destination_end));
  247. }
  248.  
  249. /* --------------------------------------------------------------------- */
  250.  
  251. int crunch_medium(unsigned char *source, unsigned char *source_end,
  252.                 unsigned char *destination, unsigned char *destination_end)
  253. {
  254.    register unsigned int control = 0;
  255.    register int shift = 0;
  256.    int count, offset, temp;
  257.  
  258.    medium_local += 66; /* i have no idea why it adds 66 */
  259.    if(!no_clear_flag)
  260.       for(medium_local = count = 0; count < 16384; count++)
  261.          medium_buffer[count] = 0;
  262.  
  263.    while((destination < destination_end) && (source < source_end))
  264.    {
  265.       control <<= 9; /* all codes are 9 bits long */
  266.       if((shift += 9) > 0)
  267.       {
  268.          control += *source++ << (8 + shift);
  269.          control += *source++ << shift;
  270.          shift -= 16;
  271.       }
  272.       if((temp = (control >> 16) & 511) >= 256)
  273.       {
  274.          *destination++ = medium_buffer[medium_local++ & 16383] = temp;
  275.       }
  276.       else
  277.       {
  278.          count = table_one[temp] + 3;
  279.          temp = table_two[temp];
  280.          control <<= temp;
  281.          if((shift += temp) > 0)
  282.          {
  283.             control += *source++ << (8 + shift);
  284.             control += *source++ << shift;
  285.             shift -= 16;
  286.          }
  287.          temp = (control >> 16) & 255;
  288.          offset = table_one[temp] << 8;
  289.          temp = table_two[temp];
  290.          control <<= temp;
  291.          if((shift += temp) > 0)
  292.          {
  293.             control += *source++ << (8 + shift);
  294.             control += *source++ << shift;
  295.             shift -= 16;
  296.          }
  297.          offset += (control >> 16) & 255;
  298.          offset = medium_local - offset - 1;
  299.          while((destination < destination_end) && (count--))
  300.             *destination++ = medium_buffer[medium_local++ & 16383] =
  301.                              medium_buffer[offset++ & 16383];
  302.       }
  303.    } /* while */
  304.  
  305. if(DEBUG)printf(" ...medium %s",((source > source_end) || (destination != destination_end)) ? "bad" : "good");
  306.    return((source > source_end) || (destination != destination_end));
  307. }
  308.  
  309. /* --------------------------------------------------------------------- */
  310.  
  311. void deep_clear()
  312. {
  313.    unsigned short count, temp;
  314.    temp = 627;
  315.    for(count = 0; count < 314; count++)
  316.    {
  317.       deep_weights[count] = 1;
  318.       deep_symbols[count] = temp;
  319.       deep_hash[temp] = count;
  320.       temp++;
  321.    }
  322.    temp = 0;
  323.    for(count = 314; count < 627; count++)
  324.    {
  325.       deep_weights[count] = deep_weights[temp] + deep_weights[temp + 1];
  326.       deep_symbols[count] = temp;
  327.       deep_hash[temp] = deep_hash[temp + 1] = count;
  328.       temp += 2;
  329.    }
  330.    deep_weights[count] = 65535;
  331.    deep_hash[temp] = 0;
  332.  
  333. if(DEBUG)printf(" ...clear");
  334. }
  335.  
  336. /* --------------------------------------------------------------------- */
  337.  
  338. void deep_scale()
  339. {
  340.    int symbol, swap, temp, weight;
  341.  
  342.    temp = 0;
  343.    for(symbol = 0; symbol < 627; symbol++)
  344.    {
  345.       if(deep_symbols[symbol] >= 627)
  346.       {
  347.          deep_weights[temp] = (deep_weights[symbol] + 1) >> 1;
  348.          deep_symbols[temp] = deep_symbols[symbol];
  349.          temp++;
  350.       }
  351.    }
  352.    temp = 0;
  353.    for(symbol = 314; symbol < 627; symbol++)
  354.    {
  355.       weight = deep_weights[temp] + deep_weights[temp + 1];
  356.       for(swap = symbol; deep_weights[swap - 1] > weight; swap--)
  357.       {
  358.         deep_weights[swap] = deep_weights[swap - 1];
  359.         deep_symbols[swap] = deep_symbols[swap - 1];
  360.       }
  361.       deep_weights[swap] = weight;
  362.       deep_symbols[swap] = temp;
  363.       temp += 2;
  364.    }
  365.    for(symbol = 0; symbol < 627; symbol++)
  366.    {
  367.       temp = deep_symbols[symbol];
  368.       deep_hash[temp] = symbol; if(temp < 627) deep_hash[temp + 1] = symbol;
  369.    }
  370.  
  371. if(DEBUG)printf(" ...scale");
  372. }
  373.  
  374. /* --------------------------------------------------------------------- */
  375.  
  376. int crunch_deep(unsigned char *source, unsigned char *source_end,
  377.                 unsigned char *destination, unsigned char *destination_end)
  378. {
  379.    register unsigned int control = 0;
  380.    register int shift = 0;
  381.    int count, offset, temp, symbol, swap, temp1, temp2;
  382.  
  383.    deep_local += 60; /* i have no idea why it adds 60 */
  384.    if(!no_clear_flag)
  385.    {
  386.       deep_clear();
  387.       for(deep_local = count = 0; count < 16384; count++)
  388.          deep_buffer[count] = 0;
  389.    }
  390.  
  391.    while((destination < destination_end) && (source < source_end))
  392.    {
  393.       count = deep_symbols[626]; /* start from the root of the trie */
  394.       do
  395.       {
  396.          if(!shift++)
  397.          {
  398.             control += *source++ << 8;
  399.             control += *source++;
  400.             shift = -15;
  401.          }
  402.          control <<= 1;
  403.          count += (control >> 16) & 1;
  404.       } while((count = deep_symbols[count]) < 627);
  405.  
  406.       if(deep_weights[626] == 32768) /* scale the trie if the weight gets too large */
  407.          deep_scale();
  408.  
  409.       symbol = deep_hash[count];
  410.       do
  411.       {
  412.          deep_weights[symbol]++; /* increase the weight of this node */
  413.          if(deep_weights[symbol + 1] < deep_weights[symbol])
  414.          {
  415.             temp1 = deep_weights[(swap = symbol)];
  416.             do
  417.             {
  418.                swap++;
  419.             } while(deep_weights[swap + 1] < temp1);
  420.             deep_weights[symbol] = deep_weights[swap];
  421.             deep_weights[swap] = temp1;
  422.             temp1 = deep_symbols[symbol];
  423.             temp2 = deep_symbols[swap];
  424.             deep_symbols[swap] = temp1;
  425.             deep_symbols[symbol] = temp2;
  426.             deep_hash[temp1] = swap; if(temp1 < 627) deep_hash[temp1 + 1] = swap;
  427.             deep_hash[temp2] = symbol; if(temp2 < 627) deep_hash[temp2 + 1] = symbol;
  428.             symbol = swap;
  429.          }
  430.       } while(symbol = deep_hash[symbol]); /* repeat until we reach root */
  431.  
  432.       if((count -= 627) < 256)
  433.       {
  434.          *destination++ = deep_buffer[deep_local++ & 16383] = count;
  435.       }
  436.       else
  437.       {
  438.          count -= 253; /* length is always at least 3 characters */
  439.          control <<= 8;
  440.          if((shift += 8) > 0)
  441.          {
  442.             control += *source++ << (8 + shift);
  443.             control += *source++ << shift;
  444.             shift -= 16;
  445.          }
  446.          temp = (control >> 16) & 255;
  447.          offset = table_one[temp] << 8;
  448.          temp = table_two[temp];
  449.          control <<= temp;
  450.          if((shift += temp) > 0)
  451.          {
  452.             control += *source++ << (8 + shift);
  453.             control += *source++ << shift;
  454.             shift -= 16;
  455.          }
  456.          offset += (control >> 16) & 255;
  457.          offset = deep_local - offset - 1;
  458.          while((destination < destination_end) && (count--))
  459.             *destination++ = deep_buffer[deep_local++ & 16383] =
  460.                              deep_buffer[offset++ & 16383];
  461.       }
  462.    } /* while */
  463.  
  464. if(DEBUG)printf(" ...deep %s",((source > source_end) || (destination != destination_end)) ? "bad" : "good");
  465.    return((source > source_end) || (destination != destination_end));
  466. }
  467.  
  468. /* --------------------------------------------------------------------- */
  469.  
  470. int make_decode_table(int number_symbols, int table_size,
  471.                       unsigned char *length, unsigned short *table)
  472. {
  473.    register unsigned char bit_num = 0;
  474.    register int symbol;
  475.    unsigned int table_mask, bit_mask, pos, fill, next_symbol, leaf;
  476.    int abort = 0;
  477.  
  478.    pos = 0;
  479.    fill = 0;
  480.    bit_mask = table_mask = 1 << table_size;
  481.  
  482.    while((!abort) && (bit_num <= table_size))
  483.    {
  484.       for(symbol = 0; symbol < number_symbols; symbol++)
  485.       {
  486.          if(length[symbol] == bit_num)
  487.          {
  488.             if((pos += bit_mask) > table_mask)
  489.             {
  490.                abort = 1;
  491.                break; /* we will overrun the table! abort! */
  492.             }
  493.             while(fill < pos)
  494.                table[fill++] = symbol;
  495.          }
  496.       }
  497.       bit_mask >>= 1;
  498.       bit_num++;
  499.    }
  500.  
  501.    if((!abort) && (pos != table_mask))
  502.    {
  503.       for(; fill < table_mask; fill++)
  504.          table[fill] = 0; /* clear the rest of the table */
  505.       next_symbol = table_mask >> 1;
  506.       pos <<= 16;
  507.       table_mask <<= 16;
  508.       bit_mask = 32768;
  509.  
  510.       while((!abort) && (bit_num <= 18))
  511.       {
  512.          for(symbol = 0; symbol < number_symbols; symbol++)
  513.          {
  514.             if(length[symbol] == bit_num)
  515.             {
  516.                leaf = pos >> 16;
  517.                for(fill = 0; fill < bit_num - table_size; fill++)
  518.                {
  519.                   if(table[leaf] == 0)
  520.                   {
  521.                      table[(next_symbol << 1)] = 0;
  522.                      table[(next_symbol << 1) + 1] = 0;
  523.                      table[leaf] = next_symbol++;
  524.                   }
  525.                   leaf = table[leaf] << 1;
  526.                   leaf += (pos >> (15 - fill)) & 1;
  527.                }
  528.                table[leaf] = symbol;
  529.                if((pos += bit_mask) > table_mask)
  530.                {
  531.                   abort = 1;
  532.                   break; /* we will overrun the table! abort! */
  533.                }
  534.             }
  535.          }
  536.          bit_mask >>= 1;
  537.          bit_num++;
  538.       }
  539.    }
  540.  
  541. if(DEBUG)printf(" ...table %s",((pos != table_mask) || abort) ? "bad" : "good");
  542.    return((pos != table_mask) || abort);
  543. }
  544.  
  545. /* --------------------------------------------------------------------- */
  546.  
  547. int crunch_heavy(unsigned char *source, unsigned char *source_end,
  548.                 unsigned char *destination, unsigned char *destination_end,
  549.                 int flag, int special)
  550. {
  551.    register unsigned int control = 0;
  552.    register int shift = 0;
  553.    int count, offset, temp;
  554.  
  555.    if(!no_clear_flag) heavy_local = 0;
  556.  
  557.    if(flag)
  558.    {
  559.       for(count = 0; count < 512; count++)
  560.          heavy_literal_len[count] = 255;
  561.       for(count = 0; count < 32; count++)
  562.          heavy_offset_len[count] = 255;
  563.       flag = 0;
  564.  
  565. /* read the literal table */
  566.       {
  567.          control <<= 9; /* get number of literals */
  568.          if((shift += 9) > 0)
  569.          {
  570.             control += *source++ << (8 + shift);
  571.             control += *source++ << shift;
  572.             shift -= 16;
  573.          }
  574.          if(offset = (control >> 16) & 511)
  575.             for(count = 0; count < offset; count++)
  576.             {
  577.                control <<= 5; /* get the length of this literal */
  578.                if((shift += 5) > 0)
  579.                {
  580.                   control += *source++ << (8 + shift);
  581.                   control += *source++ << shift;
  582.                   shift -= 16;
  583.                }
  584.                temp = (control >> 16) & 31;
  585.                heavy_literal_len[count] = (temp ? temp : 255);
  586.             }
  587.          else
  588.          {
  589.             control <<= 9; /* get the defined literal */
  590.             if((shift += 9) > 0)
  591.             {
  592.                control += *source++ << (8 + shift);
  593.                control += *source++ << shift;
  594.                shift -= 16;
  595.             }
  596.             heavy_literal_len[(control >> 16) & 511] = 0;
  597.          }
  598.  
  599.          flag |= make_decode_table(512, 12, heavy_literal_len, heavy_literal_table);
  600.       }
  601.  
  602. /* read the offset table */
  603.       {
  604.          control <<= 5; /* get number of offsets */
  605.          if((shift += 5) > 0)
  606.          {
  607.             control += *source++ << (8 + shift);
  608.             control += *source++ << shift;
  609.             shift -= 16;
  610.          }
  611.          if(offset = (control >> 16) & 31)
  612.             for(count = 0; count < offset; count++)
  613.             {
  614.                control <<= 4; /* get the length of this offset */
  615.                if((shift += 4) > 0)
  616.                {
  617.                   control += *source++ << (8 + shift);
  618.                   control += *source++ << shift;
  619.                   shift -= 16;
  620.                }
  621.                temp = (control >> 16) & 15;
  622.                heavy_offset_len[count] = (temp ? temp : 255);
  623.             }
  624.          else
  625.          {
  626.             control <<= 5; /* get the defined offset */
  627.             if((shift += 5) > 0)
  628.             {
  629.                control += *source++ << (8 + shift);
  630.                control += *source++ << shift;
  631.                shift -= 16;
  632.             }
  633.             heavy_offset_len[(control >> 16) & 31] = 0;
  634.          }
  635.          temp = heavy_offset_len[special];
  636.          heavy_offset_len[special] = heavy_offset_len[31];
  637.          heavy_offset_len[31] = temp;
  638.  
  639.          flag |= make_decode_table(32, 8, heavy_offset_len, heavy_offset_table);
  640.       }
  641.  
  642.    } /* if(flag) */
  643.  
  644.    if(!flag)
  645.    {
  646. /* prefetch 12 bits for fast huffman decoding */
  647.       control <<= 12;
  648.       if((shift += 12) > 0)
  649.       {
  650.          control += *source++ << (8 + shift);
  651.          control += *source++ << shift;
  652.          shift -= 16;
  653.       }
  654.  
  655.       while((destination < destination_end) && (source < source_end))
  656.       {
  657.  
  658. /* get a literal */
  659.          if((count = heavy_literal_table[(control >> 16) & 4095]) >= 512)
  660.          {
  661.             do /* literal is longer than 12 bits */
  662.             {
  663.                if(!shift++)
  664.                {
  665.                   control += *source++ << 8;
  666.                   control += *source++;
  667.                   shift = -15;
  668.                }
  669.                control <<= 1;
  670.                count = heavy_literal_table[((control >> 16) & 1) + (count << 1)];
  671.             } while(count >= 512);
  672.             temp = 12; /* skip the original 12 bits */
  673.          }
  674.          else
  675.          {
  676.             temp = heavy_literal_len[count];
  677.          }
  678.          control <<= temp;
  679.          if((shift += temp) > 0)
  680.          {
  681.             control += *source++ << (8 + shift);
  682.             control += *source++ << shift;
  683.             shift -= 16;
  684.          }
  685.  
  686. /* less than 256 = literal, otherwise = length of string */
  687.          if(count < 256)
  688.          {
  689.             *destination++ = heavy_buffer[heavy_local++ & 8191] = count;
  690.          }
  691.          else /* must have been a string */
  692.          {
  693.             count -= 253; /* length is always at least 3 characters */
  694.             if((offset = heavy_offset_table[(control >> 20) & 255]) >= 32)
  695.             {
  696.                do /* offset is longer than 8 bits */
  697.                {
  698.                   if(!shift++)
  699.                   {
  700.                      control += *source++ << 8;
  701.                      control += *source++;
  702.                      shift = -15;
  703.                   }
  704.                   control <<= 1;
  705.                   offset = heavy_offset_table[((control >> 20) & 1) + (offset << 1)];
  706.                } while(offset >= 32);
  707.                temp = 8; /* skip the original 8 bits */
  708.             }
  709.             else
  710.             {
  711.                temp = heavy_offset_len[offset];
  712.             }
  713.             control <<= temp;
  714.             if((shift += temp) > 0)
  715.             {
  716.                control += *source++ << (8 + shift);
  717.                control += *source++ << shift;
  718.                shift -= 16;
  719.             }
  720.  
  721.             if(offset == 31)
  722.             {
  723.                offset = heavy_last_offset;
  724.             }
  725.             else
  726.             {
  727.                if(offset)
  728.                {
  729.                   temp = offset - 1;
  730.                   offset = ((control & 268369920) | 268435456) >> (28 - temp);
  731.                   control <<= temp;
  732.                   if((shift += temp) > 0)
  733.                   {
  734.                      control += *source++ << (8 + shift);
  735.                      control += *source++ << shift;
  736.                      shift -= 16;
  737.                   }
  738.                }
  739.                heavy_last_offset = offset;
  740.             }
  741.             offset = heavy_local - offset - 1;
  742.             while((destination < destination_end) && (count--))
  743.                *destination++ = heavy_buffer[heavy_local++ & 8191] =
  744.                                 heavy_buffer[offset++ & 8191];
  745.          } /* if(string) */
  746.       }
  747.    } /* if(!flag) */
  748.  
  749. if(DEBUG)printf(" ...heavy %s",((source > source_end) || (destination != destination_end) || flag) ? "bad" : "good");
  750.    return((source > source_end) || (destination != destination_end) || flag);
  751. }
  752.  
  753. /* --------------------------------------------------------------------- */
  754.  
  755. int main(int argc, char ** argv)
  756. {
  757.  int in_file, out_file;
  758.  int result = 1; /* assume an error */
  759.  int abort = 0;
  760.  unsigned int current_track;
  761.  unsigned char pack_mode;
  762.  unsigned char *buffer;
  763.  
  764.  no_clear_flag = 0;
  765.  
  766.  if (argc >= 3)
  767.  {
  768.   DEBUG = (argc >= 4);
  769.   if((in_file = open(argv[1],0)) >= 0)
  770.   {
  771.    if(read(in_file, info_header, 4) == 4)
  772.    {
  773.     if((info_header[0] == 68) && (info_header[1] == 77) && /* DMS! */
  774.      (info_header[2] == 83) && (info_header[3] == 33))
  775.     {
  776.      if(read(in_file, archive_header, 52) == 52)
  777.      {
  778.       if(mycrc(archive_header, 50) ==
  779.        (archive_header[50] << 8) + archive_header[51]) /* header_sum */
  780.       {
  781.        if(((archive_header[44] << 8) + archive_header[45]) <= 153) /* extract_ver */
  782.        {
  783.         if((out_file = creat(argv[2],384)) >= 0)
  784.         {
  785.          high_track = ((archive_header[14]) << 8) + archive_header[15]; /* hightrack */
  786.          high_track = (high_track <= 80) ? high_track : 80;
  787.          while(!abort)
  788.          {
  789.           abort = 1; /* assume an error */
  790.           buffer = 0; /* assume an error */
  791.           if(read(in_file, track_header, 20) == 20)
  792.           {
  793.            if((track_header[0] == 84) && track_header[1] == 82) /* TR */
  794.            {
  795.             if(mycrc(track_header, 18) == ((track_header[18] << 8) + track_header[19])) /* header_sum */
  796.             {
  797.              current_track = (track_header[2] << 8) + track_header[3]; /* track */
  798.              pack_size = (track_header[6] << 8) + track_header[7]; /* pack_size */
  799.              rle_size = (track_header[8] << 8) + track_header[9]; /* rle_size */
  800.              unpack_size = (track_header[10] << 8) + track_header[11]; /* unpack_size */
  801.              pack_mode = track_header[13]; /* pack_mode */
  802.              if((pack_size + 16 < BUFFERSIZE) && (rle_size + 16 < BUFFERSIZE) &&
  803.                 (unpack_size + 16 < BUFFERSIZE)) /* allow for overrun */
  804.              {
  805.               if(read(in_file, pack_buffer, pack_size) == pack_size)
  806.               {
  807.                if(mycrc(pack_buffer, pack_size) ==
  808.                 ((track_header[16] << 8) + track_header[17])) /* data_sum */
  809.                {
  810.                 if(pack_mode < 7)
  811.                 {
  812. if(DEBUG)printf("track %d pack %d rle %d unpack %d", current_track, pack_size, rle_size, unpack_size);
  813.                  switch(track_header[13]) /* pack_mode */
  814.                  {
  815.                   case 0: /* store */
  816.                   {
  817.                    if(!crunch_store(pack_buffer, pack_buffer + pack_size,
  818.                                     unpack_buffer, unpack_buffer + unpack_size))
  819.                    buffer = unpack_buffer;
  820.                    break;
  821.                   }
  822.                   case 1: /* rle */
  823.                   {
  824.                    if(!crunch_rle(pack_buffer, pack_buffer + pack_size,
  825.                                   unpack_buffer, unpack_buffer + unpack_size))
  826.                    buffer = unpack_buffer;
  827.                    break;
  828.                   }
  829.                   case 2: /* quick */
  830.                   {
  831.                    if(!crunch_quick(pack_buffer, pack_buffer + pack_size + 16,
  832.                                     unpack_buffer, unpack_buffer + rle_size))
  833.                    if(!crunch_rle(unpack_buffer, unpack_buffer + rle_size,
  834.                                     pack_buffer, pack_buffer + unpack_size))
  835.                    buffer = pack_buffer;
  836.                    break;
  837.                   }
  838.                   case 3: /* medium */
  839.                   {
  840.                    if(!crunch_medium(pack_buffer, pack_buffer + pack_size + 16,
  841.                                      unpack_buffer, unpack_buffer + rle_size))
  842.                    if(!crunch_rle(unpack_buffer, unpack_buffer + rle_size,
  843.                                   pack_buffer, pack_buffer + unpack_size))
  844.                    buffer = pack_buffer;
  845.                    break;
  846.                   }
  847.                   case 4: /* deep */
  848.                   {
  849.                    if(!crunch_deep(pack_buffer, pack_buffer + pack_size + 16,
  850.                                    unpack_buffer, unpack_buffer + rle_size))
  851.                    if(!crunch_rle(unpack_buffer, unpack_buffer + rle_size,
  852.                                   pack_buffer, pack_buffer + unpack_size))
  853.                    buffer = pack_buffer;
  854.                    break;
  855.                   }
  856.                   case 5: /* heavy1 */
  857.                   {
  858.                    if(!crunch_heavy(pack_buffer, pack_buffer + pack_size + 16,
  859.                                    unpack_buffer, unpack_buffer + rle_size,
  860.                                    track_header[12] & 2, 13))
  861.                    {
  862.                     if(track_header[12] & 4) /* pack_flag */
  863.                     {
  864.                      if(!crunch_rle(unpack_buffer, unpack_buffer + rle_size,
  865.                                    pack_buffer, pack_buffer + unpack_size))
  866.                       buffer = pack_buffer;
  867.                     }
  868.                     else
  869.                      buffer = unpack_buffer;
  870.                    }
  871.                    break;
  872.                   }
  873.                   case 6: /* heavy2 */
  874.                   {
  875.                    if(!crunch_heavy(pack_buffer, pack_buffer + pack_size + 16,
  876.                                     unpack_buffer, unpack_buffer + rle_size,
  877.                                     track_header[12] & 2, 14))
  878.                    {
  879.                     if(track_header[12] & 4) /* pack_flag */
  880.                     {
  881.                      if(!crunch_rle(unpack_buffer, unpack_buffer + rle_size,
  882.                             pack_buffer, pack_buffer + unpack_size))
  883.                       buffer = pack_buffer;
  884.                     }
  885.                     else
  886.                      buffer = unpack_buffer;
  887.                    }
  888.                    break;
  889.                   }
  890.                  } /* switch */
  891. if(DEBUG)printf("\n");
  892.                  if(buffer)
  893.                  {
  894.                   if(mysimplecrc(buffer, unpack_size) == ((track_header[14] << 8) + track_header[15])) /* unpack_sum */
  895.                   {
  896.                    if((current_track < 1000) && (unpack_size >= 8192)) /* try and skip illegal tracks */
  897.                    {
  898.                     if(write(out_file, buffer, unpack_size) == unpack_size)
  899.                     {
  900.                      if(current_track < high_track)
  901.                      {
  902.                       no_clear_flag = track_header[12] & 1; /* pack_flag */
  903.                       abort = 0; /* continue */
  904.                      }
  905.                      else
  906.                       result = 0; /* successful completion */
  907.                     }
  908.                     else
  909.                      perror("Write()");
  910.                    }
  911.                    else
  912.                     abort = 0; /* skip this chunk */
  913.                   }
  914.                   else
  915.                    puts("CRC: Unpack_Data");
  916.                  }
  917.                  else
  918.                   puts("Extract failed");
  919.                 }
  920.                 else
  921.                  puts("Unknown Pack_Mode");
  922.                }
  923.                else
  924.                 puts("CRC: Track_Buffer");
  925.               }
  926.               else
  927.                perror("Read(Track_Data)");
  928.              }
  929.              else
  930.               puts("Unpack buffers are too small");
  931.             }
  932.             else
  933.              puts("CRC: Track_Header");
  934.            }
  935.            else
  936.             puts("Unknown Track_Header");
  937.           }
  938.           else
  939.            perror("Read(Track_Header)");
  940.          } /* while */
  941.          close(out_file);
  942.         }
  943.         else
  944.          perror("Open(Destination)");
  945.        }
  946.        else
  947.         puts("Need newer extractor");
  948.       }
  949.       else
  950.        puts("CRC: Archive_Header");
  951.      }
  952.      else
  953.       perror("Read(Archive_Header)");
  954.     }
  955.     else
  956.      puts("Unknown Info_Header");
  957.    }
  958.    else
  959.     perror("Read(Info_Header)");
  960.    close(in_file);
  961.   }
  962.   else
  963.    perror("Open(Source)");
  964.  }
  965.  else
  966.  {
  967.   puts("Usage: undms source destination");
  968.   result = 0;
  969.  }
  970.  
  971.  return(result);
  972. }
  973.  
  974. /* --------------------------------------------------------------------- */
  975.  
  976. /* Absolutely for the reader ONLY. This is basically hardcoded into */
  977. /* the program. You don't like it? TS */
  978.  
  979. /* struct Info_Header
  980. {
  981.    LONG ID;             0  : 'DMS!'
  982. } */ /* SIZE = 4 */
  983.  
  984. /* general purpose flags */
  985.  
  986. #define GENERAL_NOZERO    1<<0
  987. #define GENERAL_ENCRYPT   1<<1
  988. #define GENERAL_OPTIMIZED 1<<2
  989. #define GENERAL_BANNER    1<<3
  990.  
  991. /* serial number of creator */
  992.  
  993. #define SERIAL_NUMBER 0    /* generic */
  994.  
  995. /* cpu type of creator */
  996.  
  997. #define CPU_MC68000   1
  998. #define CPU_MC68010   2
  999. #define CPU_MC68020   3
  1000. #define CPU_MC68030   4
  1001. #define CPU_MC68040   5
  1002. #define CPU_MC68050   6
  1003. #define CPU_IAPX86    7
  1004. #define CPU_IAPX88    8
  1005. #define CPU_IAPX188   9
  1006. #define CPU_IAPX186   10
  1007. #define CPU_IAPX286   11
  1008. #define CPU_IAPX386SX 12
  1009. #define CPU_IAPX386   13
  1010. #define CPU_IAPX486   14
  1011. #define CPU_IAPX586   15
  1012.  
  1013. /* coprocessor of creator */
  1014.  
  1015. #define COPRO_MC68881    1
  1016. #define COPRO_MC68882    2
  1017. #define COPRO_IAPX87     3
  1018. #define COPRO_IAPX287    4
  1019. #define COPRO_IAPX387SX  5
  1020. #define COPRO_IAPX387    6
  1021.  
  1022. /* machine type of creator */
  1023.  
  1024. #define MACHINE_AMIGA  1
  1025. #define MACHINE_PC     2
  1026. #define MACHINE_ATARI  3
  1027. #define MACHINE_MAC    4
  1028.  
  1029. /* disk types */
  1030.  
  1031. #define DISKTYPE_AMIGA1_OFS  1
  1032. #define DISKTYPE_AMIGA1_FFS  2
  1033. #define DISKTYPE_MSDOS       3
  1034. #define DISKTYPE_AMAX        4
  1035. #define DISKTYPE_MAC         5
  1036.  
  1037. /* struct Archive_Header
  1038. {
  1039.    LONG extra;          0  : for future expansion
  1040.    LONG general;        4  : general purpose flags
  1041.    LONG timestamp;      8  : creation date of archive (seconds since 00:00:00 01-Jan-78)
  1042.    SHORT lowtrack;      12 : first track (0-85)
  1043.    SHORT hightrack;     14 : last track (0-85)
  1044.    LONG pack_size;      16 : total size of data after compression
  1045.    LONG unpack_size;    20 : total size of data before compression
  1046.    LONG serialno;       24 : serial number of creator
  1047.    SHORT cpu;           28 : CPU type of creator
  1048.    SHORT copro;         30 : CPU coprocessor of creator
  1049.    SHORT machine;       32 : machine of creator
  1050.    SHORT mextra;        34 : extra ID information (machine specific)
  1051.    SHORT speed;         36 : CPU speed (approx)
  1052.    LONG  timecreate;    38 : time to create archive
  1053.    SHORT create_ver;    42 : version of creator
  1054.    SHORT extract_ver;   44 : version needed to extract
  1055.    SHORT disktype;      46 : disk type of archive
  1056.    SHORT crunchmode;    48 : compression mode (generally) used
  1057.    SHORT header_sum;    50 : header CRC
  1058. } */ /* SIZE = 52 */
  1059.  
  1060. /* crunch mode */
  1061.  
  1062. #define CRUNCH_NOCOMP   0  /* Compression modes */
  1063. #define CRUNCH_RLE      1
  1064. #define CRUNCH_QUICK    2
  1065. #define CRUNCH_MEDIUM   3
  1066. #define CRUNCH_DEEP     4
  1067. #define CRUNCH_TESTPACK 5
  1068.  
  1069. #define CRUNCH_DLE   0x90
  1070.  
  1071. /* struct Track_Header
  1072. {
  1073.    SHORT ID;            0  : 'TR'
  1074.    SHORT track;         2  : track number -1=text
  1075.    SHORT flags;         4  : general flags
  1076.    SHORT pack_size;     6  : packed length
  1077.    SHORT rle_size;      8  : rle-packed size
  1078.    SHORT unpack_size;   10 : unpacked size
  1079.    BYTE pack_flag;      12 : general purpose compression flag
  1080.    BYTE pack_mode;      13 : compression mode
  1081.    SHORT unpack_sum;    14 : unpacked CRC
  1082.    SHORT data_sum;      16 : packed CRC
  1083.    SHORT header_sum;    18 : header CRC
  1084. } */ /* SIZE = 20 */
  1085.  
  1086. /* --------------------------------------------------------------------- */
  1087.